﻿/*
 * cannet.cpp
 *
 *  Created on: 2017年6月15日
 *      Author: work
 */

#include <dm/os/io/cannet.hpp>

#include <dm/os/log/logger.hpp>

namespace dm{
namespace os{
namespace io{

static const char* logModule = "CCannet.io.os.dm";

#ifndef PF_CAN
#define PF_CAN 29
#endif

CCannet::type_t CCannet::type()const{
	return com::CAddress::Can;
}

bool CCannet::open_in( const com::CAddress& addr ){
	const com::CCanAddr* address = addr.asCan();
	if( address ){
		if( address->getBps()!=0 ){
			char cmd[64];

			sprintf(cmd,"ifconfig %s down",address->getDevice().c_str());
			system(cmd);

			sprintf(cmd,"ip link set %s type can bitrate %d",address->getDevice().c_str(),address->getBps());
			system(cmd);

			sprintf(cmd,"ifconfig %s up",address->getDevice().c_str());
			system(cmd);
		}

		m_fd  = socket(PF_CAN, SOCK_RAW, CAN_RAW);
		if( m_fd<=0 ){
			log().error(THISMODULE "创建can socket失败");
			return false;
		}

		struct ifreq ifr;
		strcpy(ifr.ifr_name, address->getDevice().c_str());
		ioctl(m_fd, SIOCGIFINDEX, &ifr);

		struct sockaddr_can addr;
		addr.can_family = PF_CAN;
		addr.can_ifindex = ifr.ifr_ifindex;

		if (bind(m_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0){
			close();
			log().warnning(THISMODULE "绑定CAN设备失败:%s",address->getDevice().c_str());
			return false;
		}

		struct can_filter rfilter;
		rfilter.can_id   = address->getId();
		rfilter.can_mask = address->getMask();

		if( -1==setsockopt(m_fd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter)) ){
			close();
			log().warnning(THISMODULE "设置id:%d，掩码失败:%d",address->getId(),address->getMask());
			return false;
		}

		return true;
	}

	return false;
}
}
}
}
